#include "Alice/Window/WindowMngr.h"
#include "Alice/Log/Log.h"
#include "Alice/Events/EventMngr.h"

namespace Alice
{

bool WindowMngr::Init(const char* title, float width, float height)
{
    // 初始化 GLFW
    glfwInit();
    // 设置 OpenGL 版本号为 3.3
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    // 使用 OpenGL 核心模型开发
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

    m_window = glfwCreateWindow((int)width, (int)height, title, NULL, NULL);
    if (m_window == nullptr)
    {
        ALICE_ERROR("Failed to create GLFW window");
        glfwTerminate();
        return false;
    }
    // 创建 OpenGL 上下文
    glfwMakeContextCurrent(m_window);
    // 设置窗口被改变后的回调函数
    glfwSetFramebufferSizeCallback(m_window, [](GLFWwindow* window, int width, int height){
        glViewport(0, 0, width, height);
    });
    // 初始化 GLAD 管理函数指针
    // 这个工作应该总是在窗口被创建后进行
    if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
    {
        ALICE_ERROR("Failed to initialize GLAD");
        return false;
    }
    // 设置缓冲区交换间隔
    glfwSwapInterval(2);
    // 开启透明通道混合
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    // 开启深度测试会导致 2D 单平面渲染结果无法显示
    // // 开启深度测试，使得 OpenGL 能够处理深度信息
    // glEnable(GL_DEPTH_TEST);

    return true;
}

bool WindowMngr::Init(WindowInfo& window_info)
{
    m_window_info = window_info;
    return Init(
        window_info.title.c_str(),
        window_info.width, 
        window_info.height
    );
}

void WindowMngr::ClearBuffer()
{
    // 使用指定颜色清空屏幕
    glClearColor(0.36f, 0.36f, 0.36f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);
}

void WindowMngr::Update()
{
    // 交换缓冲区
    glfwSwapBuffers(m_window);
}

void WindowMngr::Destroy()
{
    glfwDestroyWindow(m_window);
    glfwTerminate();
}

void WindowMngr::ProcessEvents(EventMngr* event_mngr)
{
    glfwPollEvents();

    bool button_state_changed = true;

    if (glfwGetKey(m_window, GLFW_KEY_ESCAPE) || glfwWindowShouldClose(m_window))
    {
        event_mngr->SendEvent(Event(WINDOW_QUIT));
    }
    else if (glfwGetKey(m_window, GLFW_KEY_W))
    {
        m_buttons[ static_cast<int>(InputButtons::W) ] = 1;
    }
    else if (glfwGetKey(m_window, GLFW_KEY_A))
    {
        m_buttons[ static_cast<int>(InputButtons::A) ] = 1;
    }
    else if (glfwGetKey(m_window, GLFW_KEY_S))
    {
        m_buttons[ static_cast<int>(InputButtons::S) ] = 1;
    }
    else if (glfwGetKey(m_window, GLFW_KEY_D))
    {
        m_buttons[ static_cast<int>(InputButtons::D) ] = 1;
        Event mouse_left_event(WINDOW_MOUSE_LEFT);
        event_mngr->SendEvent(mouse_left_event);
    }
    else if (glfwGetKey(m_window, GLFW_MOUSE_BUTTON_LEFT))
    {
        // Event mouse_left_event(WINDOW_MOUSE_LEFT);
        // event_mngr->SendEvent(mouse_left_event);
    }
    else 
    {
        button_state_changed = false;
    }
    
    if (button_state_changed)
    {
        Event input_event(WINDOW_INPUT);
        input_event.SetParam("key", m_buttons);
        event_mngr->SendEvent(input_event);
    }
}

} // namespace Alice
